#pragma once
using namespace std;

#include<vector>

#include"Rect.h"
#include"Bitmap.h"
#include"DisplayObject.h"
struct AnimationData;
struct ShineData;

class Sprite : public DisplayObject{
public:
	Sprite();
	Sprite(string fileName);
	Sprite(Bitmap* bitmap);
	Sprite(int width, int height);

	vector<vector<char> > getDisplayData();
	void quickRender(char** &map, int lx, int ly);

	void setBitmap(Bitmap* bitmap);
	Bitmap* getBitmap();

	void setFrameRect();
	void setFrameRect(Rect rect);
	void setFrameRect(int x, int y, int width, int height);
	Rect getFrameRect();

	Rect getObjectRect();

	void shake(int power, int duration, double speed = 1, bool yShake = false);
	void shine(char c, int duration, bool transparent = false);

	bool getMirror();
	virtual void setMirror(bool mir);

	int getSpriteWidth() const;
	int getSpriteHeight() const;

	void setX(int x) { this->x = rx = x; }
	void setY(int y) { this->y = ry = y; }

protected:
	virtual void updateOthers();
	virtual void updateEffect();
	void updateShine();
	void updateShake();
	void processShake(int power,double dur);

	void initialiaze();
	void initialiazeEffect();
	void initialiazePosition();
	void initialiazeFrameRect();

	int rx, ry;
	int count;
	char shineChar;
	int shakePower;
	bool shakeY;
	double shakeSpeed;
	int shineDuration;
	int shakeDuration;
	bool shineTransparent;
	bool mirror;
	Bitmap* bitmap;
	Rect frameRect;
};

class Icon : public Sprite {
public:
	Icon();
	Icon(int id);

	void setIndex(int index);
	int getIndex();
protected:
	virtual int getFrameRectWidth();
	virtual int getFrameRectHeight();
	virtual int getFrameRectX();
	virtual int getFrameRectY();

	virtual void refresh();

	int index;
};


class Animation : public Sprite {
public:
	Animation(int id);
	Animation(AnimationData* data);

	void start(); void play(); void pause(); void stop();
	void setSpeed(int spd);
	int getSpeed();
	void setLoop(bool l);
	void setReverse(bool r);

	void setAutoRotate(bool r);
	bool isAutoRotate();

	int duration();
	bool isPlaying();
	bool isEnded();

	int getFrameRectWidth();
	int getFrameRectHeight();

private:
	int getFrameRectX();
	int getFrameRectY();

	void makeShineData();

	int count, frame;
	int speed;
	int lastFrame;

	bool playing;
	bool loop;
	bool reverse;
	bool autoRotate;
	AnimationData* aData;

	vector<ShineData*> shineData;
protected:
	void updateOthers();
	void updateAnimationFrame();
	void updateShineData();
	void updateFrameRect();

	int animationFunction(int c);
};


class SpriteExtend : public Sprite {
public:
	SpriteExtend();
	SpriteExtend(string fileName);
	SpriteExtend(Bitmap* bitmap);
	SpriteExtend(int width, int height);

	virtual void addAnimation(Animation ani);
	virtual void addAnimation(AnimationData* ani);
	virtual void addAnimation(Animation* ani);

	virtual void removeAnimation(Animation ani);
	virtual void removeAnimation(Animation* ani);

	Animation* getAnimation(int id);

	virtual void setMirror(bool mir);

protected:
	virtual void updateOthers();
	virtual void updateAnimations();

	vector<Animation*> animations;
};